package com.basic.ui.view

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.*
import androidx.appcompat.app.AppCompatViewInflater

/**
 * @author Peter Liu
 * @since 2023/7/20 01:36
 *
 */

object ViewFactory : AppCompatViewInflater() {
    private val registerView = hashMapOf<String, () -> View>()

    /**
     * 注册view factory
     */
    fun <T : View> registerView(clazz: Class<T>, facotry: () -> T) {
        registerView[clazz.name] = facotry
    }

    override fun createView(context: Context, name: String?, attrs: AttributeSet?): View? {
        val factory = registerView[name]
        if (factory != null) {
            return factory.invoke()
        }
        //内部使用反射
        return LayoutInflater.from(context).createView(name, null, attrs)
    }

    inline fun <reified T : View> createView(
        context: Context,
        attrs: AttributeSet? = null
    ): T? {
        return createView(context, T::class.java, attrs) as? T
    }

    /**
     * 下面的大部分代码来自于[AppCompatViewInflater.createView] 方法。
     */
    fun createView(context: Context, clazz: Class<*>, attrs: AttributeSet?): View? {
        val view: View?
        when (clazz) {
            MultiAutoCompleteTextView::class.java -> {
                view = createMultiAutoCompleteTextView(context, attrs)
            }
            AutoCompleteTextView::class.java -> {
                view = createAutoCompleteTextView(context, attrs)
            }
            EditText::class.java -> {
                view = createEditText(context, attrs)
            }
            CheckBox::class.java -> {
                view = createCheckBox(context, attrs)
            }
            RadioButton::class.java -> {
                view = createRadioButton(context, attrs)
            }
            ToggleButton::class.java -> {
                view = createToggleButton(context, attrs)
            }
            Button::class.java -> {
                view = createButton(context, attrs)
            }
            CheckedTextView::class.java -> {
                view = createCheckedTextView(context, attrs)
            }
            TextView::class.java -> {
                view = createTextView(context, attrs)
            }
            ImageButton::class.java -> {
                view = createImageButton(context, attrs)
            }
            ImageView::class.java -> {
                view = createImageView(context, attrs)
            }

            Spinner::class.java -> {
                view = createSpinner(context, attrs)
            }

            RatingBar::class.java -> {
                view = createRatingBar(context, attrs)
            }
            SeekBar::class.java -> {
                view = createSeekBar(context, attrs)
            }
            else ->                 // The fallback that allows extending class to take over view inflation
                // for other tags. Note that we don't check that the result is not-null.
                // That allows the custom inflater path to fall back on the default one
                // later in this method.
                view = createView(context, clazz.name, attrs)
        }
        return view
    }
}

inline fun <reified T : View> Context.createView(
    attrs: AttributeSet? = null,
    crossinline initFun: T.() -> Unit,
): T {
    return ViewFactory.createView<T>(this, attrs)!!.apply {
        this.initFun()
    }
}
